package com.peter.baselibrary.utils

import android.content.Context
import android.os.Environment
import android.os.storage.StorageManager
import android.text.TextUtils

import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.BufferedReader
import java.io.ByteArrayOutputStream
import java.io.Closeable
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
import java.lang.reflect.InvocationTargetException
import java.math.BigDecimal
import java.nio.charset.Charset
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream

object FileUtil {

    private val BUFFER_SIZE = 8 * 1024

    /**
     * 描述：SD卡是否能用.
     *
     * @return true 可用,false不可用
     */
    val isCanUseSD: Boolean
        get() {
            try {
                return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
            } catch (e: Exception) {
                e.printStackTrace()
            }

            return false
        }

    /**
     * 获取文件夹大小
     *
     * @param file
     * @return long
     */
    fun getFolderSize(file: File): Long {

        var size: Long = 0
        try {
            val fileList = file.listFiles()
            for (i in fileList.indices) {
                if (fileList[i].isDirectory) {
                    size = size + getFolderSize(fileList[i])

                } else {
                    size = size + fileList[i].length()

                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }

        return size
    }

    /**
     * 删除指定目录下文件及目录
     *
     * @param deleteThisPath
     * @param filePath
     * @return
     */
    fun deleteFolderFile(filePath: String, deleteThisPath: Boolean) {
        if (!TextUtils.isEmpty(filePath)) {
            deleteFolderFile(File(filePath), deleteThisPath)
        }
    }

    fun deleteFolderFile(file: File?, deleteThisPath: Boolean) {
        if (file != null) {
            try {
                if (file.isDirectory) {// 处理目录
                    val files = file.listFiles()
                    for (i in files.indices) {
                        deleteFolderFile(files[i].absolutePath, true)
                    }
                }
                if (deleteThisPath) {
                    if (!file.isDirectory) {// 如果是文件，删除
                        file.delete()
                    } else {// 目录
                        if (file.listFiles().size == 0) {// 目录下没有文件或者目录，删除
                            file.delete()
                        }
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }

        }
    }

    /**
     * 格式化单位
     *
     * @param size
     * @return
     */
    fun getFormatSize(size: Double): String {
        val kiloByte = size / 1024
        if (kiloByte < 1) {
            return size.toString() + "Byte(s)"
        }

        val megaByte = kiloByte / 1024
        if (megaByte < 1) {
            val result1 = BigDecimal(java.lang.Double.toString(kiloByte))
            return result1.setScale(2, BigDecimal.ROUND_HALF_UP)
                    .toPlainString() + "KB"
        }

        val gigaByte = megaByte / 1024
        if (gigaByte < 1) {
            val result2 = BigDecimal(java.lang.Double.toString(megaByte))
            return result2.setScale(2, BigDecimal.ROUND_HALF_UP)
                    .toPlainString() + "MB"
        }

        val teraBytes = gigaByte / 1024
        if (teraBytes < 1) {
            val result3 = BigDecimal(java.lang.Double.toString(gigaByte))
            return result3.setScale(2, BigDecimal.ROUND_HALF_UP)
                    .toPlainString() + "GB"
        }
        val result4 = BigDecimal(teraBytes)
        return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB"
    }

    fun getByteArrayFromSD(path: String): ByteArray? {
        val file = File(path)
        return getByteArrayFromSD(file)
    }

    /**
     * 描述：从sd卡中的文件读取到byte[].
     *
     * @param file sd卡中文件路径
     * @return byte[]
     */
    fun getByteArrayFromSD(file: File): ByteArray? {
        var bytes: ByteArray? = null
        var out: ByteArrayOutputStream? = null
        try {
            // SD卡是否存在
            if (!isCanUseSD) {
                return null
            }
            // 文件是否存在
            if (!file.exists()) {
                return null
            }

            val fileSize = file.length()
            if (fileSize > Integer.MAX_VALUE) {
                return null
            }

            val `in` = FileInputStream(file)
            out = ByteArrayOutputStream(1024)
            val buffer = ByteArray(1024)
            var size = 0
            while (`in`.read(buffer).apply { size = this } != -1) {
                out.write(buffer, 0, size)
            }
//            while ((size = `in`.read(buffer)) != -1) {
//                out.write(buffer, 0, size)
//            }
            `in`.close()
            bytes = out.toByteArray()

        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            if (out != null) {
                try {
                    out.close()
                } catch (e: Exception) {
                }

            }
        }
        return bytes
    }

    fun getStringFromSD(file: File): String? {
        val bytes = getByteArrayFromSD(file)
        return if (bytes != null) {
            String(bytes)
        } else null
    }

    fun writeStringFile(file: File, content: String?) {
        // SD卡是否存在
        //		if (!isCanUseSD()) {
        //			return;
        //		}
        if (content != null) {
            writeByteArray(file, content.toByteArray())
        }
    }

    /**
     * 描述：将byte数组写入文件.
     *
     * @param file
     * @param content
     */
    fun writeByteArray(file: File, content: ByteArray) {

        var fos: FileOutputStream? = null
        try {
            // 文件是否存在
            if (!file.exists()) {
                val parent = file.parentFile
                if (!parent.exists()) {
                    parent.mkdirs()
                    file.createNewFile()
                }
            }
            fos = FileOutputStream(file)
            fos.write(content)

        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            if (fos != null) {
                try {
                    fos.close()
                } catch (e: Exception) {
                }

            }
        }
    }

    /**
     * 描述：读取Assets目录的文件内容.
     *
     * @param context
     * @param name
     * @return the string
     */
    fun readAssetsByName(context: Context, name: String): String? {
        var text: String? = null
        var inputReader: InputStreamReader? = null
        var bufReader: BufferedReader? = null
        try {
            inputReader = InputStreamReader(context.assets.open(name))
            bufReader = BufferedReader(inputReader)
            var line: String? = null
            val buffer = StringBuffer()

            while (bufReader.readLine().apply { line = this } != null) {
                buffer.append(line)
            }

//            while ((line = bufReader.readLine()) != null) {
//                buffer.append(line)
//            }
            text = String(buffer.toString().toByteArray())
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            try {
                if (bufReader != null) {
                    bufReader.close()
                }
                if (inputReader != null) {
                    inputReader.close()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }

        }
        return text
    }

    /**
     * 描述：读取Raw目录的文件内容.
     *
     * @param context
     * @param id
     * @param encoding
     * @return the string
     */
    fun readRawByName(context: Context, id: Int, encoding: String): String? {
        var text: String? = null
        var inputReader: InputStreamReader? = null
        var bufReader: BufferedReader? = null
        try {
            inputReader = InputStreamReader(context.resources
                    .openRawResource(id))
            bufReader = BufferedReader(inputReader)
            var line: String? = null
            val buffer = StringBuffer()
            while (bufReader.readLine().apply { line = this } != null) {
                buffer.append(line)
            }
//            while ((line = bufReader.readLine()) != null) {
//                buffer.append(line)
//            }
            text = String(buffer.toString().toByteArray(), encoding as Charset)
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            try {
                if (bufReader != null) {
                    bufReader.close()
                }
                if (inputReader != null) {
                    inputReader.close()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }

        }
        return text
    }

    /**
     * 获取sd卡路径
     */
    fun getpath(context: Context): String {
        var extSdCard = ""
        val sm = context
                .getSystemService(Context.STORAGE_SERVICE) as StorageManager
        // 获取sdcard的路径：外置和内置
        var paths: Array<String>? = null
        try {
            paths = sm.javaClass.getMethod("getVolumePaths", *arrayOfNulls(0))
                    .invoke(sm, *arrayOfNulls(0)) as Array<String>
        } catch (e: IllegalArgumentException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        } catch (e: InvocationTargetException) {
            e.printStackTrace()
        } catch (e: NoSuchMethodException) {
            e.printStackTrace()
        }

        val esd = Environment.getExternalStorageDirectory().path
        for (i in paths!!.indices) {
            if (paths[i] == esd) {
                continue
            }
            val sdFile = File(paths[i])
            if (sdFile.canWrite()) {
                extSdCard = paths[i]
            }
        }
        val file = File(extSdCard)
        return if (!file.canWrite()) {
            Environment.getExternalStorageDirectory().path
        } else extSdCard
    }

    fun fileIsExists(strFile: File): Boolean {
        try {
            if (!strFile.exists()) {
                return false
            }
        } catch (e: Exception) {
            return false
        }

        return true
    }

    fun fileIsExists(dir: String, name: String): Boolean {
        return fileIsExists(File(dir, name))
    }

    /**
     * Unzip a zip file. Will overwrite existing files.
     *
     * @param zipFile Full path of the zip file you'd like to unzip.
     * @param location Full path of the directory you'd like to unzip to (will
     * be created if it doesn't exist).
     * @throws IOException
     */
    @Throws(IOException::class)
    fun unZip(zipFile: String, location: String) {
        unZip(FileInputStream(zipFile), location)
    }

    @Throws(IOException::class)
    fun unZip(zipFile: File, location: String) {
        unZip(FileInputStream(zipFile), location)
    }

    @Throws(IOException::class)
    fun unZip(inputStream: InputStream, location: String) {
        var location = location
        var size: Int =0
        val buffer = ByteArray(BUFFER_SIZE)

        try {
            if (!location.endsWith("/")) {
                location += "/"
            }
            val f = File(location)
            if (!f.isDirectory) {
                f.mkdirs()
            }
            val zin = ZipInputStream(BufferedInputStream(inputStream, BUFFER_SIZE))
            try {
                var ze: ZipEntry? = null
//                while ((ze = zin.nextEntry) != null) {
                while (zin.nextEntry.apply { ze = this } != null) {
                    val path = location + ze!!.name
                    val unzipFile = File(path)

                    if (ze!!.isDirectory) {
                        if (!unzipFile.isDirectory) {
                            unzipFile.mkdirs()
                        }
                    } else {
                        // check for and create parent directories if they don't
                        // exist
                        val parentDir = unzipFile.parentFile
                        if (null != parentDir) {
                            if (!parentDir.isDirectory) {
                                parentDir.mkdirs()
                            }
                        }

                        // unzip the file
                        val out = FileOutputStream(unzipFile, false)
                        val fout = BufferedOutputStream(out, BUFFER_SIZE)
                        try {
//                            while ((size = zin.read(buffer, 0, BUFFER_SIZE)) != -1) {
                            while (zin.read(buffer, 0, BUFFER_SIZE).apply { size = this } != -1) {
                                fout.write(buffer, 0, size)
                            }

                            zin.closeEntry()
                        } finally {
                            fout.flush()
                            fout.close()
                        }
                    }
                }
            } finally {
                zin.close()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            inputStream.close()
        }
    }

    fun closeQuietly(closeable: Closeable?) {
        try {
            closeable?.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }

    }
}
